#define _CRT_SECURE_NO_WARNINGS 1
#include "ThreadCache.h"
#include "CentralCache.h"

void *ThreadCache::Allocte(size_t size)
{
    assert(size <= MAX_SIZE);
    size_t index = SizeClass::ListIndex(size);
    FreeList &freeList = freeLists[index];
    if (!freeList.Empty()) {
        return freeList.Pop();
    } else {
        return FetchFromCentralCache(index, SizeClass::RoundUp(size));
    }
}

void ThreadCache::Deallocte(void *ptr, size_t size)
{
    assert(ptr);
    assert(size <= MAX_SIZE);
    size_t index = SizeClass::ListIndex(size);
    FreeList &freeList = freeLists[index];
    freeList.Push(ptr);

    // 对象个数满足一定条件内存大小
    // size_t num = SizeClass::NumMoveSize(size);
    // if (freeList.Num() >= num) {
    //     ListTooLong(freeList, num, size);
    // }
    size_t num = freeList.MaxNum();
    if (freeList.Num() >= num) {
        ListTooLong(freeList, num, size);
    }
}

void ThreadCache::ListTooLong(FreeList &freeList, size_t num, size_t size)
{
    void *start = nullptr, *end = nullptr;
    freeList.PopRange(start, end, num);

    CentralCache::GetCentralCacheInstance().ReleseListToSpans(start, size);
}

// 从中心缓存获取span
void *ThreadCache::FetchFromCentralCache(size_t index, size_t size)
{
    size_t num = std::min(SizeClass::NumMoveSize(size), freeLists[index].MaxNum());
    if (num == freeLists[index].MaxNum()) {
        // std::cout << "maxnum = " << num << std::endl;
        freeLists[index].AddMaxNum(1);
    }
    void *start = nullptr, *end = nullptr;
    size_t actualNum = CentralCache::GetCentralCacheInstance().FetchRangeObj(start, end, num, size);
    assert(actualNum);
    if (actualNum == 1) {
        return start;
    } else {
        FreeList &list = freeLists[index];
        list.PushRange(NextObj(start), end, actualNum - 1);

        return start;
    }
}
